package com.maple.mybatis.plus.utils;

import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

import javax.validation.constraints.NotNull;
import java.util.Objects;


/**
 * <p>mybatis plus代码生成器</p>
 * <p>默认情况下只生成Entity。</p>
 * <p>如需生成Controller、Service、Mapper、XML等需要设置对应值。</p>
 *
 * @author maple
 */
@Getter
@Setter
@Accessors(chain = true)
public class DefaultMybatisPlusGenerator extends AutoGenerator {

    // 默认不生成controller
    private boolean generateControllers = false;
    // 默认不生成service
    private boolean generateServices = false;
    // 默认不生成mapper
    private boolean generateMappers = false;
    // 默认不生成xml
    private boolean generateXMLs = false;
    // 默认生成Entity
    private boolean generateEntities = true;
    // 默认不强制覆盖原文件
    private boolean fileOverride = false;
    // 数据库
    private String database;
    // 作者
    private String author;
    // 模块名
    private String moduleName;
    // 表名
    private String[] tableNames;
    // 用户名
    private String username = "root";
    // 密码
    private String password = "root";
    // ip address
    private String address;

    /**
     * 构造函数，默认database、author、moduleName、tableNames为必填项（都没有默认值）
     */
    public DefaultMybatisPlusGenerator(@NotNull String database, @NotNull String author, @NotNull String moduleName, @NotNull String[] tableNames) {
        this.database = Objects.requireNonNull(database);
        this.author = Objects.requireNonNull(author);
        this.moduleName = Objects.requireNonNull(moduleName);
        this.tableNames = Objects.requireNonNull(tableNames);
    }

    private GlobalConfig getGlobalConfig(@NotNull String author) {
        String projectPath = System.getProperty("user.dir");
        String outputDir = projectPath + "/src/main/java";
        return new GlobalConfig()
                .setOutputDir(outputDir)
                .setFileOverride(this.isFileOverride())
                .setAuthor(Objects.requireNonNull(author))
                .setOpen(false)
                .setSwagger2(true);
    }

    private DataSourceConfig getDataSourceConfig(@NotNull String database) {
        String url = "jdbc:mysql://" + address + "/" + Objects.requireNonNull(database) + "?serverTimezone=Asia/Shanghai&&useUnicode=true&characterEncoding=utf-8&useSSL=false";
        return new DataSourceConfig()
                .setUrl(url)
                .setDriverName("com.mysql.cj.jdbc.Driver")
                .setUsername(username)
                .setPassword(password);
    }

    private PackageConfig getPackageConfig(@NotNull String moduleName) {
        return new PackageConfig()
                .setModuleName(Objects.requireNonNull(moduleName))
                .setParent("com.maple");
    }


    private TemplateConfig getTemplateConfig() {
        TemplateConfig templateConfig = new TemplateConfig();
        if (!this.generateControllers) {
            templateConfig.setController(null);
        }
        if (!this.generateServices) {
            templateConfig.setService(null);
            templateConfig.setServiceImpl(null);
        }
        if (!this.generateMappers) {
            templateConfig.setMapper(null);
        }
        if (!this.generateXMLs) {
            templateConfig.setXml(null);
        }
        if (!this.generateEntities) {
            templateConfig.setEntity(null);
        }
        return templateConfig;
    }

    /**
     * 一次性设置controllers、services、mappers、XMLs、entities生成策略
     */
    public DefaultMybatisPlusGenerator setTemplateConfig(
            Boolean generateControllers,
            Boolean generateServices,
            Boolean generateMappers,
            Boolean generateXMLs,
            Boolean generateEntities
    ) {
        this.generateControllers = generateControllers == null ? false : generateControllers;
        this.generateServices = generateServices == null ? false : generateServices;
        this.generateMappers = generateMappers == null ? false : generateMappers;
        this.generateXMLs = generateXMLs == null ? false : generateXMLs;
        this.generateEntities = generateEntities == null ? true : generateEntities;
        return this;
    }

    private FreemarkerTemplateEngine getDefaultTemplateEngine() {
        return new FreemarkerTemplateEngine();
    }

    private StrategyConfig getStrategyConfig(@NotNull String[] tableNames, @NotNull String moduleName) {
        return new StrategyConfig()
                .setNaming(NamingStrategy.underline_to_camel)
                .setColumnNaming(NamingStrategy.underline_to_camel)
                .setEntityLombokModel(true)
                .setRestControllerStyle(true)
//                .setSuperEntityColumns("id")
                .setInclude(Objects.requireNonNull(tableNames))
                .setControllerMappingHyphenStyle(true)
                .setTablePrefix(Objects.requireNonNull(moduleName) + "_");
    }

    @Override
    public void execute() {
        if (this.getGlobalConfig() == null) {
            this.setGlobalConfig(this.getGlobalConfig(Objects.requireNonNull(author)));
        }
        if (this.getDataSource() == null) {
            this.setDataSource(this.getDataSourceConfig(Objects.requireNonNull(database)));
        }
        if (this.getPackageInfo() == null) {
            this.setPackageInfo(this.getPackageConfig(Objects.requireNonNull(moduleName)));
        }
        if (this.getTemplateEngine() == null) {
            this.setTemplateEngine(this.getDefaultTemplateEngine());
        }
        if (this.getTemplate() == null) {
            this.setTemplate(this.getTemplateConfig());
        }
        if (this.getStrategy() == null) {
            this.setStrategy(this.getStrategyConfig(Objects.requireNonNull(tableNames), Objects.requireNonNull(moduleName)));
        }
        super.execute();
    }
}
